GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 1b02fd...6d1c18 )
by Joss
01:06
created

anchor.js ➔ ... ➔ this.add   C

Complexity

Conditions 11
Paths 52

Size

Total Lines 111

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 11
c 1
b 0
f 0
nc 52
nop 1
dl 0
loc 111
rs 5.2653

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like anchor.js ➔ ... ➔ this.add often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/*!
2
 * AnchorJS - v1.2.1 - 2015-07-02
3
 * https://github.com/bryanbraun/anchorjs
4
 * Copyright (c) 2015 Bryan Braun; Licensed MIT
5
 */
6
7
function AnchorJS(options) {
8
  'use strict';
9
10
  this.options = options || {};
11
12
  this._applyRemainingDefaultOptions = function(opts) {
13
    this.options.icon = this.options.hasOwnProperty('icon') ? opts.icon : '\ue9cb'; // Accepts characters (and also URLs?), like  '#', '¶', '❡', or '§'.
14
    this.options.visible = this.options.hasOwnProperty('visible') ? opts.visible : 'hover'; // Also accepts 'always'
15
    this.options.placement = this.options.hasOwnProperty('placement') ? opts.placement : 'right'; // Also accepts 'left'
16
    this.options.class = this.options.hasOwnProperty('class') ? opts.class : ''; // Accepts any class name.
17
  };
18
19
  this._applyRemainingDefaultOptions(options);
20
21
  this.add = function(selector) {
22
    var elements,
23
        elsWithIds,
24
        idList,
25
        elementID,
26
        i,
27
        roughText,
28
        tidyText,
29
        index,
30
        count,
31
        newTidyText,
32
        readableID,
33
        anchor;
34
35
    this._applyRemainingDefaultOptions(this.options);
36
37
    // Provide a sensible default selector, if none is given.
38
    if (!selector) {
39
      selector = 'h1, h2, h3, h4, h5, h6';
40
    } else if (typeof selector !== 'string') {
41
      throw new Error('The selector provided to AnchorJS was invalid.');
42
    }
43
44
    elements = document.querySelectorAll(selector);
45
    if (elements.length === 0) {
46
      return false;
47
    }
48
49
    this._addBaselineStyles();
50
51
    // We produce a list of existing IDs so we don't generate a duplicate.
52
    elsWithIds = document.querySelectorAll('[id]');
53
    idList = [].map.call(elsWithIds, function assign(el) {
54
      return el.id;
55
    });
56
57
    for (i = 0; i < elements.length; i++) {
58
59
      if (elements[i].hasAttribute('id')) {
60
        elementID = elements[i].getAttribute('id');
61
      } else {
62
        roughText = elements[i].textContent;
63
64
        // Refine it so it makes a good ID. Strip out non-safe characters, replace
65
        // spaces with hyphens, truncate to 32 characters, and make toLowerCase.
66
        //
67
        // Example string:                                // '⚡⚡⚡ Unicode icons are cool--but they definitely don't belong in a URL fragment.'
68
        tidyText = roughText.replace(/[^\w\s-]/gi, '')    // ' Unicode icons are cool--but they definitely dont belong in a URL fragment'
69
                                .replace(/\s+/g, '-')     // '-Unicode-icons-are-cool--but-they-definitely-dont-belong-in-a-URL-fragment'
70
                                .replace(/-{2,}/g, '-')   // '-Unicode-icons-are-cool-but-they-definitely-dont-belong-in-a-URL-fragment'
71
                                .substring(0, 64)         // '-Unicode-icons-are-cool-but-they-definitely-dont-belong-in-a-URL'
72
                                .replace(/^-+|-+$/gm, '') // 'Unicode-icons-are-cool-but-they-definitely-dont-belong-in-a-URL'
73
                                .toLowerCase();           // 'unicode-icons-are-cool-but-they-definitely-dont-belong-in-a-url'
74
75
        // Compare our generated ID to existing IDs (and increment it if needed)
76
        // before we add it to the page.
77
        newTidyText = tidyText;
78
        count = 0;
79
        do {
80
          if (index !== undefined) {
81
            newTidyText = tidyText + '-' + count;
82
          }
83
          // .indexOf is supported in IE9+.
84
          index = idList.indexOf(newTidyText);
85
          count += 1;
86
        } while (index !== -1);
87
        index = undefined;
88
        idList.push(newTidyText);
89
90
        // Assign it to our element.
91
        // Currently the setAttribute element is only supported in IE9 and above.
92
        elements[i].setAttribute('id', newTidyText);
93
94
        elementID = newTidyText;
95
      }
96
97
      readableID = elementID.replace(/-/g, ' ');
98
99
      // The following code builds the following DOM structure in a more effiecient (albeit opaque) way.
100
      // '<a class="anchorjs-link ' + this.options.class + '" href="#' + elementID + '" aria-label="Anchor link for: ' + readableID + '" data-anchorjs-icon="' + this.options.icon + '"></a>';
101
      anchor = document.createElement('a');
102
      anchor.className = 'anchorjs-link ' + this.options.class;
103
      anchor.href = '#' + elementID;
104
      anchor.setAttribute('aria-label', 'Anchor link for: ' + readableID);
105
      anchor.setAttribute('data-anchorjs-icon', this.options.icon);
106
107
      if (this.options.visible === 'always') {
108
        anchor.style.opacity = '1';
109
      }
110
111
      if (this.options.icon === '\ue9cb') {
112
        anchor.style.fontFamily = 'anchorjs-icons';
113
        anchor.style.fontStyle = 'normal';
114
        anchor.style.fontVariant = 'normal';
115
        anchor.style.fontWeight = 'normal';
116
        anchor.style.lineHeight = 1;
117
      }
118
119
      if (this.options.placement === 'left') {
120
        anchor.style.position = 'absolute';
121
        anchor.style.marginLeft = '-1em';
122
        anchor.style.paddingRight = '0.5em';
123
        elements[i].insertBefore(anchor, elements[i].firstChild);
124
      } else { // if the option provided is `right` (or anything else).
125
        anchor.style.paddingLeft = '0.375em';
126
        elements[i].appendChild(anchor);
127
      }
128
    }
129
130
    return this;
131
  };
132
133
  this.remove = function(selector) {
134
    var domAnchor,
135
        elements = document.querySelectorAll(selector);
136
    for (var i = 0; i < elements.length; i++) {
137
      domAnchor = elements[i].querySelector('.anchorjs-link');
138
      if (domAnchor) {
139
        elements[i].removeChild(domAnchor);
140
      }
141
    }
142
    return this;
143
  };
144
145
  this._addBaselineStyles = function() {
146
    // We don't want to add global baseline styles if they've been added before.
147
    if (document.head.querySelector('style.anchorjs') !== null) {
148
      return;
149
    }
150
151
    var style = document.createElement('style'),
152
        linkRule =
153
        ' .anchorjs-link {'                       +
154
        '   opacity: 0;'                          +
155
        '   text-decoration: none;'               +
156
        '   -webkit-font-smoothing: antialiased;' +
157
        '   -moz-osx-font-smoothing: grayscale;'  +
158
        ' }',
159
        hoverRule =
160
        ' *:hover > .anchorjs-link,'              +
161
        ' .anchorjs-link:focus  {'                +
162
        '   opacity: 1;'                          +
163
        ' }',
164
        anchorjsLinkFontFace =
165
        ' @font-face {'                           +
166
        '   font-family: "anchorjs-icons";'       +
167
        '   font-style: normal;'                  +
168
        '   font-weight: normal;'                 + // Icon from icomoon; 10px wide & 10px tall; 2 empty below & 4 above
169
        '   src: url(data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMg8SBTUAAAC8AAAAYGNtYXAWi9QdAAABHAAAAFRnYXNwAAAAEAAAAXAAAAAIZ2x5Zgq29TcAAAF4AAABNGhlYWQEZM3pAAACrAAAADZoaGVhBhUDxgAAAuQAAAAkaG10eASAADEAAAMIAAAAFGxvY2EAKACuAAADHAAAAAxtYXhwAAgAVwAAAygAAAAgbmFtZQ5yJ3cAAANIAAAB2nBvc3QAAwAAAAAFJAAAACAAAwJAAZAABQAAApkCzAAAAI8CmQLMAAAB6wAzAQkAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADpywPA/8AAQAPAAEAAAAABAAAAAAAAAAAAAAAgAAAAAAADAAAAAwAAABwAAQADAAAAHAADAAEAAAAcAAQAOAAAAAoACAACAAIAAQAg6cv//f//AAAAAAAg6cv//f//AAH/4xY5AAMAAQAAAAAAAAAAAAAAAQAB//8ADwABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAQAAAAAAAAAAAAIAADc5AQAAAAACADEARAJTAsAAKwBUAAABIiYnJjQ/AT4BMzIWFxYUDwEGIicmND8BNjQnLgEjIgYPAQYUFxYUBw4BIwciJicmND8BNjIXFhQPAQYUFx4BMzI2PwE2NCcmNDc2MhcWFA8BDgEjARQGDAUtLXoWOR8fORYtLTgKGwoKCjgaGg0gEhIgDXoaGgkJBQwHdR85Fi0tOAobCgoKOBoaDSASEiANehoaCQkKGwotLXoWOR8BMwUFLYEuehYXFxYugC44CQkKGwo4GkoaDQ0NDXoaShoKGwoFBe8XFi6ALjgJCQobCjgaShoNDQ0NehpKGgobCgoKLYEuehYXAAEAAAABAACiToc1Xw889QALBAAAAAAA0XnFFgAAAADRecUWAAAAAAJTAsAAAAAIAAIAAAAAAAAAAQAAA8D/wAAABAAAAAAAAlMAAQAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAAAAAACAAAAAoAAMQAAAAAACgAUAB4AmgABAAAABQBVAAIAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAADgCuAAEAAAAAAAEADgAAAAEAAAAAAAIABwCfAAEAAAAAAAMADgBLAAEAAAAAAAQADgC0AAEAAAAAAAUACwAqAAEAAAAAAAYADgB1AAEAAAAAAAoAGgDeAAMAAQQJAAEAHAAOAAMAAQQJAAIADgCmAAMAAQQJAAMAHABZAAMAAQQJAAQAHADCAAMAAQQJAAUAFgA1AAMAAQQJAAYAHACDAAMAAQQJAAoANAD4YW5jaG9yanMtaWNvbnMAYQBuAGMAaABvAHIAagBzAC0AaQBjAG8AbgBzVmVyc2lvbiAxLjAAVgBlAHIAcwBpAG8AbgAgADEALgAwYW5jaG9yanMtaWNvbnMAYQBuAGMAaABvAHIAagBzAC0AaQBjAG8AbgBzYW5jaG9yanMtaWNvbnMAYQBuAGMAaABvAHIAagBzAC0AaQBjAG8AbgBzUmVndWxhcgBSAGUAZwB1AGwAYQByYW5jaG9yanMtaWNvbnMAYQBuAGMAaABvAHIAagBzAC0AaQBjAG8AbgBzRm9udCBnZW5lcmF0ZWQgYnkgSWNvTW9vbi4ARgBvAG4AdAAgAGcAZQBuAGUAcgBhAHQAZQBkACAAYgB5ACAASQBjAG8ATQBvAG8AbgAuAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==) format("truetype");' +
170
        ' }',
171
        pseudoElContent =
172
        ' [data-anchorjs-icon]::after {'          +
173
        '   content: attr(data-anchorjs-icon);'   +
174
        ' }',
175
        firstStyleEl;
176
177
    style.className = 'anchorjs';
178
    style.appendChild(document.createTextNode('')); // Necessary for Webkit.
179
180
    // We place it in the head with the other style tags, if possible, so as to
181
    // not look out of place. We insert before the others so these styles can be
182
    // overridden if necessary.
183
    firstStyleEl = document.head.querySelector('[rel="stylesheet"], style');
184
    if (firstStyleEl === undefined) {
185
      document.head.appendChild(style);
186
    } else {
187
      document.head.insertBefore(style, firstStyleEl);
188
    }
189
190
    style.sheet.insertRule(linkRule, style.sheet.cssRules.length);
191
    style.sheet.insertRule(hoverRule, style.sheet.cssRules.length);
192
    style.sheet.insertRule(pseudoElContent, style.sheet.cssRules.length);
193
    style.sheet.insertRule(anchorjsLinkFontFace, style.sheet.cssRules.length);
194
  };
195
}
196
197
var anchors = new AnchorJS();
198